<template>
  <canvas ref="threePractice" class="three-practice"></canvas>
</template>

<script>
import * as THREE from 'three';

import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

export default {
  name: 'threejsPractice',
  mounted () {
    this.initThree()
  },
  methods: {
    initThree() {
      // 创建场景
      const scene = new THREE.Scene()

      // 创建相机
      const camera = new THREE.PerspectiveCamera(
        45, // 视角
        window.innerWidth / window.innerHeight, // 宽高比
        0.1, // 近平面
        1000 // 远平面
      )

      // 渲染器
      const renderer = new THREE.WebGLRenderer()
      renderer.setSize(window.innerWidth, window.innerHeight)
      document.body.appendChild(renderer.domElement)

      // 创建几何体
      const cubegeometry = new THREE.BoxGeometry(1, 1, 1)
      // 创建材质
      const cubematerial0 = new THREE.MeshBasicMaterial({
        color: 0x00ff00,
        // 线框
        wireframe: true
      })
      const cubematerial1 = new THREE.MeshBasicMaterial({
        color: 0xff0000,
        // 线框
        wireframe: true
      })
      const cubematerial2 = new THREE.MeshBasicMaterial({
        color: 0x0000ff,
        // 线框
        wireframe: true
      })
      const cubematerial3 = new THREE.MeshBasicMaterial({
        color: 0xffff00,
        // 线框
        wireframe: true
      })
      const cubematerial4 = new THREE.MeshBasicMaterial({
        color: 0x00ffff,
        // 线框
        wireframe: true
      })
      const cubematerial5 = new THREE.MeshBasicMaterial({
        color: 0xff00ff,
        // 线框
        wireframe: true
      })
      // 立方体不同的面设置不同的材质
      const cube = new THREE.Mesh(cubegeometry, [cubematerial0, cubematerial1, cubematerial2,
        cubematerial3, cubematerial4, cubematerial5])

      cube.position.x = 2

      scene.add(cube)


      // 创建几何体
      const geometry = new THREE.BufferGeometry()
      /*// 创建顶点数据，顶点是有序的，每三个为一个顶点，逆时针为正面
      const vertices = new Float32Array([
        -1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0
      ])
      // 创建顶点属性
      geometry.setAttribute("position", new  THREE.BufferAttribute(vertices, 3))*/

      // 使用索引绘制，顶点数据
      const vertices = new Float32Array([
        -1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, -1.0, 1.0, 0
      ])
      // 创建顶点属性
      geometry.setAttribute("position", new  THREE.BufferAttribute(vertices, 3))
      // 使用索引创建三角形（共用顶点）
      const indices = new Uint16Array([0, 1, 2, 2, 3, 0])
      // 创建索引属性
      geometry.setIndex(new THREE.BufferAttribute(indices, 1))

      // 设置2个顶点组，不同的三角形使用不同的材质
      geometry.addGroup(0, 3, 0)
      geometry.addGroup(3, 3, 1)

      // 创建材质
      const material = new THREE.MeshBasicMaterial({
        color: 0x00ff00,
        // 两面都可以看到
        side: THREE.DoubleSide
      })
      const material1 = new THREE.MeshBasicMaterial({
        color: 0xff0000,
        // 两面都可以看到
        side: THREE.DoubleSide
      })
      const plane = new THREE.Mesh(geometry, [material, material1])
      scene.add(plane)

      // 设置相机位置
      camera.position.x = 2
      camera.position.z = 5
      camera.position.y = 2
      camera.lookAt(0, 0, 0)

      // 添加世界坐标辅助器（线段长度）
      const axesHelper = new THREE.AxesHelper(5);
      scene.add(axesHelper)

      // 添加轨道控制器
      const controls = new OrbitControls(camera, renderer.domElement)
      // 设置带阻尼的惯性
      controls.enableDamping = true
      // 设置阻尼系数
      controls.dampingFactor = 0.05
      // 设置旋转速度
      // controls.autoRotate = true

      // 渲染场景
      renderer.render(scene, camera)

      const animate = () => {
        controls.update()

        requestAnimationFrame(animate)
        // 旋转
        /*cube.rotation.x += 0.01
        cube.rotation.y += 0.01*/

        // 渲染
        renderer.render(scene, camera)
      }
      animate()

      // 监听窗口变化
      window.addEventListener('resize', () => {
        // 重置渲染器宽高比
        renderer.setSize(window.innerWidth, window.innerHeight)
        // 重置相机宽高比
        camera.aspect = window.innerWidth / window.innerHeight
        // 更新相机投影矩阵
        camera.updateProjectionMatrix()
      })

      let btn = document.createElement("button")
      btn.innerHTML = "点击全屏"
      btn.style.position = "absolute"
      btn.style.top = "10px"
      btn.style.left = "10px"
      btn.style.zIndex = "999"
      btn.onclick = function () {
        // 全屏
        document.body.requestFullscreen()
      }
      document.body.appendChild(btn)

      // 退出全屏按钮
      let exitBtn = document.createElement("button")
      exitBtn.innerHTML = "退出全屏"
      exitBtn.style.position = "absolute"
      exitBtn.style.top = "10px"
      exitBtn.style.left = "100px"
      exitBtn.style.zIndex = "999"
      exitBtn.onclick = function () {
        // 全屏
        document.exitFullscreen()
      }
      document.body.appendChild(exitBtn)
    },
  }
}
</script>

<style scoped>
.three-practice {
  position: fixed;
  top: 0;
  left: 0;
}
</style>
